import 'dart:io';
import 'dart:convert';
import 'dart:typed_data';
import 'package:path_provider/path_provider.dart';
import 'package:crypto/crypto.dart';
import 'package:sinosheets/utils/common_utils/log_util.dart';
import 'dart:math';

class GBWebViewCache {
  static const String _cacheDir = 'webview_cache';
  static const String _versionFileName = 'version.txt';

  /// 单例模式
  static final GBWebViewCache _instance = GBWebViewCache._internal();
  factory GBWebViewCache() => _instance;
  GBWebViewCache._internal();

  /// 缓存的版本号
  String? _currentVersion;

  /// 初始化缓存系统
  Future<void> init() async {
    try {
      // 确保缓存目录存在
      final cacheDir = await _getCacheDir();
      if (!await cacheDir.exists()) {
        await cacheDir.create(recursive: true);
      }

      // 加载版本信息
      await _loadVersionInfo();
    } catch (e) {
      LogUtil.e('WebView缓存初始化失败: $e');
    }
  }

  /// 获取缓存目录
  Future<Directory> _getCacheDir() async {
    final appDir = await getApplicationDocumentsDirectory();
    return Directory('${appDir.path}/$_cacheDir');
  }

  /// 加载版本信息
  Future<void> _loadVersionInfo() async {
    try {
      final versionFile = await _getVersionFile();
      if (await versionFile.exists()) {
        _currentVersion = await versionFile.readAsString();
      }
    } catch (e) {
      LogUtil.e('加载版本信息失败: $e');
    }
  }

  /// 获取版本文件
  Future<File> _getVersionFile() async {
    final cacheDir = await _getCacheDir();
    return File('${cacheDir.path}/$_versionFileName');
  }

  /// 更新版本信息
  Future<void> updateVersion(String newVersion) async {
    try {
      // 如果版本相同，说明内容没有变化
      if (newVersion == _currentVersion) {
        return;
      }

      final versionFile = await _getVersionFile();
      await versionFile.writeAsString(newVersion);
      _currentVersion = newVersion;

      // 如果版本不同，清除所有缓存文件（除了版本文件）
      await _clearCacheExceptVersion();
    } catch (e) {
      LogUtil.e('更新版本信息失败: $e');
    }
  }

  /// 清除除了版本文件外的所有缓存
  Future<void> _clearCacheExceptVersion() async {
    try {
      final cacheDir = await _getCacheDir();
      if (await cacheDir.exists()) {
        final entities = await cacheDir.list().toList();
        for (var entity in entities) {
          if (entity is File && !entity.path.endsWith(_versionFileName)) {
            await entity.delete();
          }
        }
      }
    } catch (e) {
      LogUtil.e('清除缓存文件失败: $e');
    }
  }

  /// 生成缓存文件路径
  Future<String> _generateCachePath(String url) async {
    final cacheDir = await _getCacheDir();
    final fileName = md5.convert(utf8.encode(url)).toString();
    return '${cacheDir.path}/$fileName';
  }

  /// 检查文件是否已缓存
  Future<bool> isCached(String url) async {
    final path = await _generateCachePath(url);
    return File(path).exists();
  }

  /// 从缓存加载文件
  Future<Uint8List?> loadFromCache(String url) async {
    try {
      final path = await _generateCachePath(url);
      final file = File(path);
      if (await file.exists()) {
        return await file.readAsBytes();
      }
    } catch (e) {
      LogUtil.e('从缓存加载文件失败: $e');
    }
    return null;
  }

  /// 保存文件到缓存
  Future<void> saveToCache(String url, Uint8List data) async {
    try {
      final path = await _generateCachePath(url);
      await File(path).writeAsBytes(data);
    } catch (e) {
      LogUtil.e('保存文件到缓存失败: $e');
    }
  }

  /// 清除缓存
  Future<void> clearCache() async {
    try {
      final cacheDir = await _getCacheDir();
      if (await cacheDir.exists()) {
        await cacheDir.delete(recursive: true);
      }
      _currentVersion = null;
    } catch (e) {
      LogUtil.e('清除缓存失败: $e');
    }
  }

  /// 获取缓存信息
  Future<Map<String, dynamic>> getCacheInfo() async {
    try {
      final cacheDir = await _getCacheDir();
      if (!await cacheDir.exists()) {
        return {
          'size': 0,
          'count': 0,
          'files': <String>[],
          'version': _currentVersion,
        };
      }

      int totalSize = 0;
      int fileCount = 0;
      List<String> files = [];

      final entities = await cacheDir.list().toList();
      for (var entity in entities) {
        if (entity is File) {
          final stat = await entity.stat();
          totalSize += stat.size;
          fileCount++;
          files.add(entity.path.split('/').last);
        }
      }

      return {
        'size': totalSize,
        'count': fileCount,
        'files': files,
        'version': _currentVersion,
      };
    } catch (e) {
      LogUtil.e('获取缓存信息失败: $e');
      return {
        'size': 0,
        'count': 0,
        'files': <String>[],
        'version': _currentVersion,
      };
    }
  }

  /// 获取可读的缓存大小
  String getReadableCacheSize(int bytes) {
    if (bytes <= 0) return "0 B";
    const suffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
    var i = (log(bytes) / log(1024)).floor();
    return '${(bytes / pow(1024, i)).toStringAsFixed(2)} ${suffixes[i]}';
  }
}
